import cv2
import time
import os
import threading
import logging
from datetime import datetime
from flask import Flask, jsonify
from flask_cors import CORS
from ultralytics import YOLOv10
from qcloud_cos import CosConfig, CosS3Client

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)

# 全局配置
CONFIG = {
    # COS配置
    'cos': {
        'bucket_name': 'hujiaqi-1358073331',
        'region': 'ap-guangzhou',
        'secret_id': 'AKIDuuiJhsqa9UbUWbklojfYDfvxlNn2A8tQ',
        'secret_key': 'Ogw7BEvSnvpUwHWkrwwnStENI0UnvqY2',
        'detections_folder': 'fire_detections/'
    },
    # 视频检测配置
    'detection': {
        'model_path': "models/YOLOv10-FireSmoke-M.pt",
        'image_size': 640,
        'conf_threshold': 0.1,
        'output_dir': "detected_frames",
        'save_interval': 5  # 保存间隔(秒)
    },
    # Flask配置
    'api': {
        'host': '0.0.0.0',
        'port': 5000
    }
}

class VideoDetector:
    def __init__(self):
        self.running = False
        self.model = YOLOv10(CONFIG['detection']['model_path'])
        os.makedirs(CONFIG['detection']['output_dir'], exist_ok=True)
        
    def detect_frame(self, frame):
        """执行目标检测"""
        results = self.model.predict(
            source=frame,
            imgsz=CONFIG['detection']['image_size'],
            conf=CONFIG['detection']['conf_threshold']
        )
        return results[0].plot(), len(results[0].boxes) > 0

    def process_video(self, video_path):
        """处理视频文件"""
        self.running = True
        cap = cv2.VideoCapture(video_path)
        if not cap.isOpened():
            logger.error(f"无法打开视频文件: {video_path}")
            return
            
        total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
        last_save_time = 0
        
        logger.info(f"开始处理视频: {video_path} (总帧数: {total_frames})")
        
        while self.running:
            ret, frame = cap.read()
            if not ret:
                break
                
            # 执行检测
            processed_frame, has_detection = self.detect_frame(frame)
            
            # 保存检测结果
            current_time = time.time()
            if has_detection and (current_time - last_save_time) >= CONFIG['detection']['save_interval']:
                timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
                filename = f"detection_{timestamp}.jpg"
                output_path = os.path.join(CONFIG['detection']['output_dir'], filename)
                cv2.imwrite(output_path, processed_frame)
                last_save_time = current_time
                logger.info(f"保存检测结果: {output_path}")
            
            # 显示实时画面
            cv2.imshow("YOLOv10 实时检测", processed_frame)
            if cv2.waitKey(1) & 0xFF == ord('q'):
                break
                
        cap.release()
        cv2.destroyAllWindows()
        logger.info("视频处理完成")
        self.running = False

    def stop(self):
        """停止视频处理"""
        self.running = False

class COSUploader:
    def __init__(self):
        self.running = False
        config = CosConfig(
            Region=CONFIG['cos']['region'],
            SecretId=CONFIG['cos']['secret_id'],
            SecretKey=CONFIG['cos']['secret_key']
        )
        self.client = CosS3Client(config)
        
    def upload_file(self, local_path):
        """上传单个文件到COS"""
        try:
            if not os.path.exists(local_path):
                logger.warning(f"文件不存在: {local_path}")
                return False
                
            filename = os.path.basename(local_path)
            cos_key = CONFIG['cos']['detections_folder'] + filename
            
            # 上传文件
            self.client.put_object_from_local_file(
                Bucket=CONFIG['cos']['bucket_name'],
                LocalFilePath=local_path,
                Key=cos_key
            )
            
            # 获取访问URL
            image_url = f"https://{CONFIG['cos']['bucket_name']}.cos.{CONFIG['cos']['region']}.myqcloud.com/{cos_key}"
            logger.info(f"上传成功: {image_url}")
            
            # 上传成功后删除本地文件
            os.remove(local_path)
            return True
            
        except Exception as e:
            logger.error(f"上传失败: {str(e)}")
            return False

    def monitor_and_upload(self):
        """监控文件夹并上传新文件"""
        self.running = True
        logger.info("开始监控上传文件夹...")
        
        while self.running:
            try:
                # 获取文件夹内所有jpg文件
                files = [
                    os.path.join(CONFIG['detection']['output_dir'], f) 
                    for f in os.listdir(CONFIG['detection']['output_dir'])
                    if f.lower().endswith(('.jpg', '.jpeg', '.png'))
                ]
                
                for file_path in files:
                    if self.upload_file(file_path):
                        time.sleep(0.5)  # 避免频繁上传
                        
                time.sleep(1)  # 每1秒检查一次
                
            except Exception as e:
                logger.error(f"上传线程错误: {str(e)}")
                time.sleep(5)
                
    def stop(self):
        """停止上传服务"""
        self.running = False

def create_flask_app(uploader):
    """创建Flask应用"""
    app = Flask(__name__)
    CORS(app)
    
    @app.route('/api/detections', methods=['GET'])
    def get_detections():
        """获取所有检测结果图片信息"""
        try:
            response = uploader.client.list_objects(
                Bucket=CONFIG['cos']['bucket_name'],
                Prefix=CONFIG['cos']['detections_folder'],
                MaxKeys=1000
            )

            detections = []
            if 'Contents' in response:
                for item in response['Contents']:
                    if not item['Key'].endswith('/'):
                        image_url = f"https://{CONFIG['cos']['bucket_name']}.cos.{CONFIG['cos']['region']}.myqcloud.com/{item['Key']}"
                        
                        detections.append({
                            'filename': item['Key'].split('/')[-1],
                            'url': image_url,
                            'size': item['Size'],
                            'last_modified': item['LastModified'],
                            'storage_class': item['StorageClass']
                        })

            return jsonify({
                'count': len(detections),
                'detections': detections
            }), 200

        except Exception as e:
            logger.error(f"获取检测结果失败: {str(e)}")
            return jsonify({
                'error': '获取检测结果失败',
                'message': str(e)
            }), 500

    @app.route('/api/health', methods=['GET'])
    def health_check():
        """健康检查接口"""
        return jsonify({'status': 'healthy'}), 200
        
    return app

def main():
    # 初始化各模块
    detector = VideoDetector()
    uploader = COSUploader()
    app = create_flask_app(uploader)
    
    # 启动视频检测线程
    def run_detector():
        detector.process_video("1.mp4")
    
    detector_thread = threading.Thread(target=run_detector)
    detector_thread.daemon = True
    
    # 启动上传线程
    upload_thread = threading.Thread(target=uploader.monitor_and_upload)
    upload_thread.daemon = True
    
    # 启动Flask服务线程
    def run_flask():
        app.run(
            host=CONFIG['api']['host'],
            port=CONFIG['api']['port'],
            use_reloader=False
        )
    
    flask_thread = threading.Thread(target=run_flask)
    flask_thread.daemon = True
    
    # 启动所有线程
    detector_thread.start()
    upload_thread.start()
    flask_thread.start()
    
    logger.info("所有服务已启动")
    logger.info(f"API服务地址: http://{CONFIG['api']['host']}:{CONFIG['api']['port']}")
    
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        logger.info("正在停止服务...")
        detector.stop()
        uploader.stop()
        detector_thread.join()
        upload_thread.join()
        logger.info("服务已停止")

if __name__ == "__main__":
    main()